#include "common.h"
#include "ThreadCache.h"
#include "PageCache.h"

#ifndef CONCURRENTALLOC_H
#define CONCURRENTALLOC_H


static void* ConcurrentAlloc(size_t size)
{
	if (size > MAX_BYTES)
	{
		size_t alignSize = SizeClass::RoundUp(size);
		size_t k = alignSize >> PAGE_SHIFT;

		PageCache::GetInstance()->_pageMtx.lock();
		Span* span = PageCache::GetInstance()->NewSpan(k);
		span->_blockSize = size;
		PageCache::GetInstance()->_pageMtx.unlock();

		void* ptr = (void*)(span->_pageId << PAGE_SHIFT);

		return ptr;
	}
	else
	{
		if (pTLSThreadCache == nullptr)
		{
			static MemoryPool<ThreadCache> tcPool;
			tcPool._poolMtx.lock();
			pTLSThreadCache = tcPool.New();
			tcPool._poolMtx.unlock();
		}

		return pTLSThreadCache->Allocate(size);
	}
}

static void ConcurrentFree(void* ptr) 
{
	assert(ptr);

	Span* span = PageCache::GetInstance()->MapBlockToSpan(ptr);
	size_t size = span->_blockSize;

	if (size > MAX_BYTES)
	{
		PageCache::GetInstance()->_pageMtx.lock();
		PageCache::GetInstance()->ReleaseSpanToPageCache(span);
		PageCache::GetInstance()->_pageMtx.unlock();
	}
	else
	{
		pTLSThreadCache->Deallocate(ptr, size);
	}
		
}


#endif // !CONCURRENTALLOC_H